package drds.global_transaction.resource_manager.execute;

import drds.global_transaction.api.global_transaction_id_context.GlobalTransactionIdContexts;
import drds.global_transaction.resource_manager.model.Column;
import drds.global_transaction.resource_manager.model.TableMetaData;
import drds.global_transaction.resource_manager.model.TableMetaDatas;
import drds.global_transaction.resource_manager.proxy.resource_manager.StatementProxy;
import drds.global_transaction.resource_manager.sql_recognizer.SqlRecognizer;

import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;

@SuppressWarnings("rawtypes")
public abstract class AbstractExecutor<T, S extends Statement> implements Executor
{

	protected SqlRecognizer sqlRecognizer;
	protected StatementProxy<S> statementProxy;
	protected StatementExecuteTemplate<T, S> statementExecuteTemplate;
	private TableMetaData tableMetaData;

	public AbstractExecutor(SqlRecognizer sqlRecognizer, StatementProxy<S> statementProxy, StatementExecuteTemplate<T, S> statementExecuteTemplate)
	{
		this.sqlRecognizer = sqlRecognizer;
		this.statementProxy = statementProxy;
		this.statementExecuteTemplate = statementExecuteTemplate;
	}

	//
	protected String buildWhereConditionForPrimaryKeyColumnList(List<Column> columnList) throws SQLException
	{
		StringBuilder sb = new StringBuilder();
		int size = columnList.size();
		for (int i = 0; i < size; i++)
		{
			Column column = columnList.get(i);
			sb.append(column.getName() + " = ?");
			if (i < (size - 1))
			{
				sb.append(" or ");
			}
		}
		return sb.toString();
	}

	protected abstract Object doExecute(Object... args) throws Exception;

	@Override
	public Object execute(Object... args) throws Exception
	{
		String globalTransactionIdWithAddressAndPort = GlobalTransactionIdContexts.getGlobalTransactionIdWithAddressAndPort();
		statementProxy.getConnectionProxy().bind(globalTransactionIdWithAddressAndPort);
		return doExecute(args);
	}

	//
	protected TableMetaData getTableMetaData()
	{
		return getTableMetaData(sqlRecognizer.getTableName());
	}

	protected TableMetaData getTableMetaData(String tableName)
	{
		if (tableMetaData != null)
		{
			return tableMetaData;
		}
		tableMetaData = TableMetaDatas.getTableMetaData(statementProxy.getConnectionProxy().getDataSourceProxy(), tableName);
		return tableMetaData;
	}

}
